
package ListHandling;

import basic.Bike;
import basic.Client;
import basic.DateClass;
import basic.Reservation;
import basic.ReservationStatus;
import exceptions.BadDataException;
import exceptions.BikeNotAvailableException;
import exceptions.ObjectNotFound;
import java.util.Date;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import lists.Lists;

public class ReservationListHandling {
   
    private static final Logger logger = Logger.getLogger("lab2_generic.ListHandling.ReservationListHandling");
    
    public static Scanner in = new Scanner(System.in);
    
    //*******************************************************************
    public static void addReservation() throws BikeNotAvailableException, BadDataException {
        
        
        logger.entering("ReservationListHandling", "addReservation");
        int[] id2 = new int[2];    // id2[0] - client ID ; id2[1] - bike ID
        System.out.println("Enter ID of client: ");
        id2[0] = in.nextInt();
        if ( Lists.cList.ifExist(id2[0])<0 ) 
        {
            logger.exiting("ReservationListHandling", "addReservation - BAD CLIENT ID ENTERED");
            throw new BadDataException();
        }

        System.out.println("Enter ID of bike: ");
        id2[1] = in.nextInt();
        if ( Lists.bList.ifExist(id2[1])<0 ) 
        {
             logger.exiting("ReservationListHandling", "addReservation - BAD BIKE ID ENTERED");
            throw new BadDataException();
        }

        // if we are here that means entered ID values are propriet
        Date hDate = null;
        Date rDate = null;
    
        try{
        
            System.out.println("Enter hire date:");
            hDate = DateClass.readDate();
            System.out.println("Enter return date:");
            rDate = DateClass .readDate();
            
            int p = DateClass.compare(rDate, hDate);
            if ( p < 0  ) {
                logger.exiting("ReservationListHandling", "addReservation - ENTERED RETURN DATE IS SMALLER THAN HIRE DATE");
                throw new BadDataException();
            } // return date is "smaller" than hire date 
              
         } catch (Exception e){
              logger.exiting("ReservationListHandling", "addReservation - BAD DATE FORMAT HAS BEEN ENTERED");
              throw new BadDataException();   // here - bad date has been  entered
         }
    
         // now all necessary date is entered; first we need to check if for specified bike 
         // reservation is possible - if date intervals dont overlap
        
          boolean possible  = true;  
          try{
                for( Entry<Integer, DateClass> entry : Lists.bList.getObj(id2[1]).reservations.entrySet() ) {
//                    logger.log(Level.WARNING, "ENTRY OBJECT: {0}", entry);
                if (  !entry.getValue().check(hDate, rDate)  ) {
                    possible = false; 
                    break;
                    } 
                }
          } catch (ObjectNotFound e){ } // object must exist   
         
          if (!possible) {
              logger.exiting("ReservationListHandling", "addReservation - BIKE IS NOT AVAILABLE  IN ENTERED DATE INTERVAL");
              throw new BikeNotAvailableException();
          } // date overlaps !
          else
          {
              logger.log(Level.INFO, "addReservation - CREATING A NEW RESERVATION OBJECT"); 
              Reservation res = new Reservation(id2[0], id2[1], hDate, rDate, ReservationStatus.BOOKED );
              try{
                  Lists.rList.add(res);
                  Bike bike = Lists.bList.getObj( id2[1] );
                  bike.reservations.put( res.getId(), new DateClass(hDate, rDate));
                  logger.exiting("ReservationListHandling", "addReservation -  ");
                 
              } catch(ObjectNotFound e){ }
              
          }
    
         
        }
    
    
    //*******************************************************************
    public static void finalizeReservation() throws ObjectNotFound, BadDataException {
            
           logger.entering("ReservationListHandling", "finalizeReservation");
           System.out.println("Enter reservation ID: ");
           int id = in.nextInt();
           Reservation helper;
           
           helper = Lists.rList.getObj(id);  // that can throw expepction ObjectNotFound
                    
           if ( helper.getStatus()!=ReservationStatus.IN_REALIZATION ){
               logger.exiting("ReservationListHandling", "finalizeReservation - RESERVATION STATUS IS NOT VALID DO FINALIZE ");
               throw new BadDataException(); // only IN_REALIZATION reservation can be finalized
           }
           else {
               
               System.out.println("Mileage: ");
               int m = in.nextInt();
               helper.setStatus(ReservationStatus.COMPLETED);
               helper.setCost( Lists.bList.getObj( helper.getBikeId() ).getPpd()*DateClass.diffInDays(helper.getHireDate(), helper.getReturnDate() ) );
               Bike b =  Lists.bList.getObj( helper.getBikeId() );
               b.changeMileage(m);
               b.reservations.remove( helper.getId() );
               logger.exiting("ReservationListHandling", "finalizeReservation - RESERVATION FINALIZED ");

                              
           }
                
    }
    
    //*******************************************************************
    @SuppressWarnings("empty-statement")
    public static void cancelReservation() throws BadDataException, ObjectNotFound {
        
        logger.entering("ReservationListHandling", "cancelReservation");
        System.out.println("Enter reservation ID: ");
        int id = in.nextInt();
        Reservation helper;
        
        helper = Lists.rList.getObj(id);
          
           
           if ( helper.getStatus()!=ReservationStatus.BOOKED ){
               
               logger.exiting("ReservationListHandling", "cancelReservation - RESERVATION STATUS IS NOT VALID DO CANCEL ");
               throw new BadDataException(); // only BOOKED reservation can be canceled
           }
               
           else {
               
               helper.setStatus(ReservationStatus.CANCELED);
               Bike b= Lists.bList.getObj( helper.getBikeId() );
               b.reservations.remove( helper.getId() );
               logger.exiting("ReservationListHandling", "cancelReservation - RESERVATION CANCELED");               
           }
        
        
    }
    
    
    
    //*******************************************************************
    @SuppressWarnings("empty-statement")
    public static void activeReservation() throws BadDataException, ObjectNotFound {
        
        logger.entering("ReservationListHandling", "activeReservation");
        System.out.println("Enter reservation ID: ");
        int id = in.nextInt();
        Reservation helper;
        
        helper = Lists.rList.getObj(id);
          
           
           if ( helper.getStatus()!=ReservationStatus.BOOKED ){
               
               logger.exiting("ReservationListHandling", "activeReservation - RESERVATION STATUS IS NOT VALID TO ACTIVATE");
               throw new BadDataException(); // only BOOKED reservation can be activacetd 
           }
              
           else {
               
               helper.setStatus(ReservationStatus.IN_REALIZATION);
               Client c =  Lists.cList.getObj( helper.getClientId() );
               c.incCount();
               logger.exiting("ReservationListHandling", "activeReservation - RESERVATION ACTIVATED");
                                                  
           }
        
    }
    
    
    public static void sort() {
        Lists.bList.sort();
        System.out.println("Successfully sorted!");
    }
    
    public static void show(){
        
        System.out.println("RESERVATION LIST\n");
        System.out.println(String.format("%4s %10s %10s %12s %12s %15s %5s",
                "ID", "CLIENT ID", "BIKE ID", "HIRE DATE", "RETURN DATE", "STATUS", "COST"));
        Lists.rList.show();
    }
    
    
}